
<!-- 低代码 主页面：用于编辑详情页  eui-page-frame-->

<template>
	<eui-background type="common" >
		<view class="lowcode-nav-wrap"><eui-nav-bar :title="state?.pageTitle" color="#333"  /></view>
		<view class="lowcode-edit-wrap" :style="state.editWrapStyle" v-if="state?.mainFormData" >
			<eui-card :title="state?.mainCardTitle" class="lowcode-bill-detail-edit-card-wrap" hPadding="28" type="single">
				<view class="lowcode-title-line" v-if="state?.mainCardTitle" />
				<view class="lowcode-page-card-cnt-wrap" :style="state.mainCardStyle">
					<view class="lowcode-page-card-cnt">
						<view v-for="(colField, idx) in state?.mainFormPanel?.Components" :key="idx" class="lowcode-components-item">
							<DynamicComponent v-if="fieldNeedShow(colField, { pGuid: state.mainFormPanel?.c_guid })" :conf-object="colField" :data-object="state.mainFormData" @handleDynamicChange="handleMainDynamicChange" :md-code="props?.LowcodeGuid" />
						</view>
					</view>
					<view class="lowcode-page-sub-card-panel" v-for="(mainSubCardFormPanel, pIdx) in getMainSubCardFormPanels()">
						<view class="lowcode-page-sub-card-chead-wrap" v-if="mainSubCardFormPanel?.c_name" >
							<text class="lowcode-card-title item-text item-text-detail">{{ mainSubCardFormPanel?.c_name }}</text>
						</view>
						<view class="lowcode-title-line" v-if="mainSubCardFormPanel?.c_name" />
						<view class="lowcode-page-sub-card-cnt" v-if="mainSubCardFormPanel?.Components?.length">
							<eui-row v-for="(rowCols, fIdx) in mainSubCardFormPanel?.Components" :key="fIdx" class="lowcode-page-row-wrap">
								<eui-col v-for="(colField, cfIdx) in rowCols" :key="cfIdx" class="lowcode-page-col" :span="colField?.c_col_span || 12">
									<eui-text v-if="fieldNeedShow(colField, { showPattern: true })" cWidth="width: 100%" v-bind="state.subCellProps?.['main_sub'+(mainSubCardFormPanel?.c_guid || '')+fIdx+'_'+cfIdx]" />
									<UploadFile v-else-if="colField?.c_type === 'fileupload'" :readonly="true" :autoUpload="false" serviceName="EnjoyMain" fileMediatype="image" :fileId="state?.mainFormData?.[colField.c_code || '']" fileClass="lowcode"
										return-type="array" mode="grid" :imageStyles="{ width:74,height:74 }" :customFetchUniqueKey="LOWCODERUNTIMEUNIQUEKEY" customFetchMethodName="FetchLowcodeFile" />
								</eui-col>
							</eui-row>
						</view>
					</view>
				</view>
			</eui-card>
			<eui-card v-if="state.otherPanelConf" :title="state?.otherCardTitle" class="lowcode-bill-detail-edit-card-wrap" hPadding="28" type="single">
				<template v-if="state.c_menuCFG?.some?.(m => m.menuCode === 'AddRow')" v-slot:extra><view class="extra-view">
					<eui-uicons  color="#888888" style="margin-left: 32rpx;" type="plusempty" size="30" @click="handleAddRow()" />
				</view></template>
				<view class="lowcode-title-line" v-if="state?.otherPanelConf?.ComponentsHeade?.length" />
				<view class="lowcode-edit-page-tb-row-wrap" v-for="(rowData, rowIdx) in state.otherPanelData" :key="rowIdx">
					<view class="lowcode-edit-page-tb-row-title">
						<view class="edit-page-tb-row-title-txt">第{{ (+rowIdx || 0) + 1 }}行</view>
						<view class="edit-page-tb-row-icons">
							<eui-uicons v-if="state.c_menuCFG?.some?.(m => m.menuCode === 'DeleteRow')" color="#888888" type="trash" size="30" @click="handleDelRow(+rowIdx)" />
							<eui-uicons  color="#888888" style="margin-left: 32rpx;" type="compose" size="30" @click="handleEditRow(rowData, +rowIdx)" />
						</view>
					</view>
					<view class="lowcode-page-card-cnt" v-if="state?.otherPanelConf?.Components?.length">
						<eui-row v-for="(rowCols, fIdx) in state?.otherPanelConf?.Components" :key="fIdx" class="lowcode-page-row-wrap">
							<eui-col v-for="(colField, cfIdx) in rowCols" :key="cfIdx" class="lowcode-page-col" :span="colField?.c_col_span || 12">
								<eui-text v-if="fieldNeedShow(colField, { showPattern: true })" cWidth="width: 100%" v-bind="state.cellProps?.[rowIdx+'_'+fIdx+'_'+cfIdx]" />
								<UploadFile v-else-if="colField?.c_type === 'fileupload'" :readonly="true" :autoUpload="false" serviceName="EnjoyMain" fileMediatype="image" :fileId="rowData?.[colField?.c_code || '']" fileClass="lowcode"
									return-type="array" mode="grid" :imageStyles="{ width:74,height:74 }" :customFetchUniqueKey="LOWCODERUNTIMEUNIQUEKEY" customFetchMethodName="FetchLowcodeFile" />
							</eui-col>
						</eui-row>
					</view>
					<view class="lowcode-page-sub-card-panel" v-for="(otherSubCardFormPanel, pIdx) in getOtherSubCardFormPanels()">
						<view class="lowcode-page-sub-card-chead-wrap" v-if="otherSubCardFormPanel?.c_name" >
							<text class="lowcode-card-title item-text item-text-detail">{{ otherSubCardFormPanel?.c_name }}</text>
						</view>
						<view class="lowcode-title-line" v-if="otherSubCardFormPanel?.c_name" />
						<view class="lowcode-page-sub-card-cnt" v-if="otherSubCardFormPanel?.Components?.length">
							<eui-row v-for="(rowCols, fIdx) in otherSubCardFormPanel?.Components" :key="fIdx" class="lowcode-page-row-wrap">
								<eui-col v-for="(colField, cfIdx) in rowCols" :key="cfIdx" class="lowcode-page-col" :span="colField?.c_col_span || 12">
									<eui-text v-if="fieldNeedShow(colField, { showPattern: true })" cWidth="width: 100%" v-bind="state.subCellProps?.['other_sub'+(otherSubCardFormPanel?.c_guid || '')+rowIdx+'_'+fIdx+'_'+cfIdx]" />
									<UploadFile v-else-if="colField?.c_type === 'fileupload'" :readonly="true" :autoUpload="false" serviceName="EnjoyMain" fileMediatype="image" :fileId="rowData?.[colField?.c_code || '']" fileClass="lowcode"
										return-type="array" mode="grid" :imageStyles="{ width:74,height:74 }" :customFetchUniqueKey="LOWCODERUNTIMEUNIQUEKEY" customFetchMethodName="FetchLowcodeFile" />
								</eui-col>
							</eui-row>
						</view>
					</view>
				</view>
			</eui-card>
		</view>
		<view class="lowcode-page-btm-btns-wrap" >
			<eui-fab v-if="state.menusCFGMore?.length" class="lowcode-card-btm-btn-more" direction="vertical" :content="state.menusCFGMore" @trigger="handleMoreBtnClick" >
				<eui-uicons color="#888888" type="more-filled" size="30" />
			</eui-fab>
			<eui-button
				v-for="(mCFG, mIdx) in state.menusCFG"
				:key="mIdx"
				:type="getMenuBtnType(mCFG, mIdx)"
				:title="mCFG.menuTitle"
				:singleTag="mCFG.menuCode"
				:disabled="mBtnDis(mCFG)"
				@buttonClick="handleBtnClick"
				class="lowcode-page-btm-btn"
			/>
		</view>
		<eui-popup ref="popupRef" class="lowcode-create-popup-wrap" background-color="#f8f8f8" type="bottom" :mask-click="false">
			<view class="lowcode-popup-content" :style="state.createPopupStyle">
				<view class="lowcode-popup-title">
					<view class="lowcode-popup-title-txt" >{{ state.editTbIdx === undefined ? "新增行" : "修改行" }}</view>
					<view class="lowcode-popup-cancel" @tap="handlePopupClose">
						<eui-uicons type="closeempty" size="40" color="#888888" />
					</view>
				</view>
				<scroll-view scroll-y class="lowcode-popup-default-content">
					<view v-for="(colField, idx) in state.otherPanelShow?.Components" :key="idx" class="lowcode-components-item">
						<DynamicComponent v-if="fieldNeedShow(colField, { pGuid: state.otherPanelShow?.c_guid })" :conf-object="colField" :data-object="state.popupData" @handleDynamicChange="handlePopDynamicChange" parentSrc="3" :md-code="props?.LowcodeGuid" />
					</view>
				</scroll-view>
			</view>
			<view class="lowcode-popup-bottom flex-1 flex">
				<eui-button type="max2" title="重置" singleTag="重置" @buttonClick="handlePopupClose"></eui-button>
				<eui-button type="max" title="确认" singleTag="确认" @buttonClick="handlePopupClose"></eui-button>
			</view>
		</eui-popup>
		<eui-popup ref="popupAuditRef" class="lowcode-create-popup-wrap" background-color="#f8f8f8" type="bottom" :mask-click="false">
			<view class="lowcode-popup-content" >
				<view class="lowcode-popup-title"><view class="lowcode-popup-title-txt" >输入工作密码</view></view>
				<view class="lowcode-popup-default-content">
					<eui-card-input :value="'[' + store?.state?.value?.main?.loginInfo?.sUser + ']' + store?.state?.value?.main?.loginInfo?.sUserName" title="审核用户" type="textname" />
					<eui-card-input v-model="workPwd" title="工作密码" type="password" />
				</view>
			</view>
			<view class="lowcode-popup-bottom flex-1 flex">
				<eui-button type="max2" title="取消" singleTag="取消" @buttonClick="handleAuditClose"></eui-button>
				<eui-button type="max" title="确认" singleTag="确认" @buttonClick="handleAuditClose"></eui-button>
			</view>
		</eui-popup>
	</eui-background>
</template>

<script setup lang="ts" >
import { ref } from "vue";
import { onLoad, onReady, onShow } from "@dcloudio/uni-app";

import store from "@/store";
import serviceTools from '@/common/service';
import useService from "@/hooks/useService";
import { initRdsDict, getRdsSysConfig } from "@/hooks/init";
import UploadFile from "@/components/UploadFile.vue";

import DynamicComponent from "../dynamicComponent/index.vue";
import useLowcodeSystemInfo from "../hooks/useSystemInfo";
import type { LowcodeBtnEvent, LowcodeFieldNeedShowProxy, LowcodeGridRowColComponents, LowcodeMenuItemCFG, LowcodePage, LowcodePagePanel, LowcodePagePanelComponentItem, LowcodeRect } from "../interface";
import { EBillApproveStatus, EBillStatus, ECBillApproveStatus, ECBillStatus, lowcodeDebounceTime, lowcodePrimaryLink, lowcodeRowKey, LOWCODERUNTIMEMOBILEUNIQUEKEY, LOWCODERUNTIMEUNIQUEKEY, LOWCODEUNIQUEKEY } from "../constant";
import type { MdEditDetailState, BillDetailFetchReq, BillDetailFetchRes, FetchDetailDataReq, FetchDetailDataRes, FetchMdBillDetailProxy, MdBillDetailProps } from "./interface";
import useComponentProps from "../hooks/useComponentProps";
import useLowcodeDef from "../hooks/useLowcodeDef";
import { formGridSort, handlePanelEditFields, lowcodeDebounce } from "../utils";
import useLowcodeDataEvent from "../hooks/useLowcodeDataEvent";
import useLowcodeValidator from "../hooks/useLowcodeValidator";
import useLowcodeMenuBtns from "../hooks/useLowcodeMenuBtns";

const props = defineProps<MdBillDetailProps>();
const service = useService({ prefix: "mainApi" });
const state = ref<MdEditDetailState>({
	tableSaveData: { DelList: [], NewList: [], ModifiedList: [] },
	validateErrorDataPop: {},
	validateErrorDataPage: {},
}), popupRef = ref();
const workPwd = ref(""), workPwdBillId = ref(), popupAuditRef = ref();
const { getSystemInfo } = useLowcodeSystemInfo();
const { getComponentProps } = useComponentProps();
const { generateLowcodeDef } = useLowcodeDef({ mdCode: props?.LowcodeGuid });
const { handleEventData } = useLowcodeDataEvent({ mdCode: props?.LowcodeGuid });
const { handleValidator } = useLowcodeValidator({ mdCode: props?.LowcodeGuid });
const { handleSaveBill: handleSaveBillHook, handleAuditBill: handleAuditBillHook, handleAuditValidate: handleAuditValidateHook } = useLowcodeMenuBtns();

const getMainCardTitle = () => state.value?.mainFormPanel?.c_name || "";

const getOtherCardTitle = () => state.value?.otherPanelConf?.c_name || "";

const getMainSubCardFormPanels = () => {
	const mainSubCardFormGuid = state.value?.mainFormPanel?.c_guid;
	const mainSubCardFormPanels = state.value?.subCardFormPanels?.[mainSubCardFormGuid  || ""];
	return mainSubCardFormPanels;
}

const getOtherSubCardFormPanels = () => {
	const otherSubCardFormGuid = state.value?.otherPanelConf?.c_guid;
	const otherSubCardFormPanels = state.value?.subCardFormPanels?.[otherSubCardFormGuid  || ""];
	return otherSubCardFormPanels;
};

const getMenuBtnType = (mCFG: LowcodeMenuItemCFG, mIdx: number) => {
	if (mIdx + 1 === state.value?.menusCFG?.length) {
		return "min";
	}
	return "min2";
};

const mBtnDis = (mCFG: LowcodeMenuItemCFG) => {
	let btnDis = false; // TODO 新建和审批，权限码里不包含这两个，要不要根据权限码判断禁用
	const mdLimit = state.value?.mdInfo?.c_limitcode || "R";	// c_limitcode: "RWSAOICUXDBP"
	const enableApprove = state.value.enableApprove;
	const c_status = state.value?.mainFormData?.c_status || EBillStatus.尚未审核;
	const appStatus = state.value?.mainFormData?.c_approve_status || EBillApproveStatus.尚未审批;

	if (mCFG.menuCode === "APPROVE") { // 审批
		const isNotApproved = c_status === EBillStatus.尚未审核 || c_status === ECBillStatus.NotApproved; // 尚未审核
    const isNotYetApproved = appStatus === EBillApproveStatus.NotYetApproved || appStatus === ECBillApproveStatus.NotYetApproved; // 尚未审批
    const isApprovalPassed = (appStatus === EBillApproveStatus.ApprovalPassed || appStatus === ECBillApproveStatus.ApprovalPassed); // 审批已通过
		btnDis = !(enableApprove ? (isNotApproved || isApprovalPassed) : (isNotYetApproved ? false : true));
		// if ([EBillApproveStatus.正在审批, EBillApproveStatus.ApprovalProgress].includes(appStatus)) {
		// 	btnDis = true;
		// }
		// if (!mdLimit.includes("E")) {
		// 	btnDis = true;
		// }
	}
	if (mCFG.menuCode === "DeleteBill" && !mdLimit.includes("D")) {
		btnDis = true; 	// 删单
	}
	if (mCFG.menuCode === "Cancel" && !mdLimit.includes("C")) {
		btnDis = true;	 // 作废
	}
	if (mCFG.menuCode === "AUDIT") {
		const isNotApproved = c_status === EBillStatus.尚未审核 || c_status === ECBillStatus.NotApproved; // 尚未审核
		const isApprovalPassed = (appStatus === EBillApproveStatus.ApprovalPassed || appStatus === ECBillApproveStatus.ApprovalPassed); // 审批已通过
		const isApprovving = (appStatus === EBillApproveStatus.ApprovalProgress || appStatus === ECBillApproveStatus.ApprovalProgress); // 正在审批
		btnDis = !(isNotApproved && (enableApprove ? isApprovalPassed : true)) || isApprovving;
		if (!mdLimit.includes("A")) {
			btnDis = true; 	 // 审核
		}
		// btnDis = false; // TODO remove
	}
	// if (mCFG.menuCode === "NEWBILL" && !mdLimit.includes("D")) {
	// 	btnDis = true;	 // 新单
	// }
	return btnDis;
};

const hasFieldChanged = () => {
	const { initMainFormData, initOtherPanelData, mainFormData, otherPanelData } = state.value || {};
	const fieldKeyAry = Object.keys(mainFormData || {});
	let isChanged = false;

	for (let idx = 0; idx < fieldKeyAry?.length; idx++) {
		if (isChanged) {
			break;
		}
		const fk = fieldKeyAry[idx];
		const fv = mainFormData[fk], initFV = initMainFormData[fk];
		if (fv !== initFV) {
			isChanged = true;
		}
	}

	if (!isChanged) {
		if (otherPanelData?.length !== initOtherPanelData?.length) {
			isChanged = true;
		} else {
			for (let idx = 0; idx < otherPanelData?.length; idx++) {
				if (isChanged) {
					break;
				}
				const rowIdxDataSave = otherPanelData[idx], rowIdxDataInit = initOtherPanelData[idx];

				const rowFieldKeyAry = Object.keys(rowIdxDataSave || {});

				for (let idx = 0; idx < rowFieldKeyAry?.length; idx++) {
					if (isChanged) {
						break;
					}
					const fRowk = rowFieldKeyAry[idx];
					const fRowV = rowIdxDataSave[fRowk], initRowV= rowIdxDataInit[fRowk];
					if (fRowV !== initRowV) {
						isChanged = true;
					}
				} // for
			} // for
		} // if else
	} // if

	return isChanged;
};

const handleMoreBtnClick = (...rest) => {
	console.log("handleMoreBtnClick ", rest);
}

const	handleAuditClose = async ({ singleTag }) => {
	if (singleTag === "取消") {
		return popupAuditRef.value?.close();
	}
	const userNo = store?.state?.value?.main?.loginInfo?.sUser;
	const userName = store?.state?.value?.main?.loginInfo?.sUserName;
	if (!workPwd.value) {
		return serviceTools.enjoyShowToast(`请录入[${userNo}]${userName}的审核密码！`);
	}

	const p = { InputAuditUserNo: userNo, MdCode: props.LowcodeGuid, WkPassword: workPwd.value };
	const validateAuditRes = await handleAuditValidateHook(p);
	if (validateAuditRes) {
		return serviceTools.enjoyShowToast(validateAuditRes);
	}
	const fetcRes = await handleAuditBillHook({ ...workPwdBillId.value });
	if (fetcRes) {
		const mdInfoEdit = typeof props?.mdInfo === "string" ? props?.mdInfo : (props?.mdInfo ? JSON.stringify(props?.mdInfo) : "");
		uni.navigateTo({ url: `../lowcode/billDetail/index?billId=${workPwdBillId.value?.billId}&LowcodeGuid=${props?.LowcodeGuid}&LowcodeDetailGuid=${props.LowcodeDetailGuid}&mdInfo=${mdInfoEdit}` });
		popupAuditRef.value?.close();
	}
};

const handleBtnClick = async (btnEvent?: LowcodeBtnEvent) => {
	let fetchBillId = props?.billId;
	const hasFieldChangedRes = hasFieldChanged();
	const mdInfoEdit = typeof props?.mdInfo === "string" ? props?.mdInfo : (props?.mdInfo ? JSON.stringify(props?.mdInfo) : "");
	console.log("handleBtnClick ", btnEvent, hasFieldChangedRes, state); // DeleteBill
	if (btnEvent?.singleTag === "AUDIT") {
		if (!fetchBillId || hasFieldChangedRes) {
			const saveBeforeAuditRes = await handleBtnClick({ singleTag: "SaveBill", src: "AUDIT" });
			if (typeof saveBeforeAuditRes === "string") {
				fetchBillId = saveBeforeAuditRes;
			} else {
				return;
			}
    }
		state.value.billIdAfterSave = fetchBillId;

		let asyncConfirmRes = false;
		const userNo = store?.state?.value?.main?.loginInfo?.sUser;
    const useWorkPass: string = await getRdsSysConfig("系统参数", "是否使用工作密码");

    if (useWorkPass === "确认提示") {
      const content = "请确认是否要审核当前单据？";
      asyncConfirmRes = await new Promise<boolean>((resolve, _) => uni.showModal({ title: "提示", content: content, success: (res) => res.confirm ? resolve(true) : resolve(false) }));
			if (!asyncConfirmRes) {
				return;
			}
			const fetcRes = await handleAuditBillHook({ BillId: fetchBillId, UserNo: userNo, ModuleCode: props.LowcodeGuid });
			fetcRes && uni.navigateTo({ url: `../lowcode/billDetail/index?billId=${fetchBillId}&LowcodeGuid=${props?.LowcodeGuid}&LowcodeDetailGuid=${props.LowcodeDetailGuid}&mdInfo=${mdInfoEdit}` });
    }

		if(useWorkPass === "是") {
			workPwdBillId.value = { BillId: fetchBillId, UserNo: userNo, ModuleCode: props.LowcodeGuid };
			popupAuditRef.value?.open();
    }
		return false;
	}
	if (btnEvent?.singleTag === "APPROVE") {
		if (!fetchBillId || hasFieldChangedRes) {
			const saveBeforeAuditRes = await handleBtnClick({ singleTag: "SaveBill", src: "AUDIT" });
			if (typeof saveBeforeAuditRes === "string") {
				fetchBillId = saveBeforeAuditRes;
			} else {
				return;
			}
    }
		state.value.billIdAfterSave = fetchBillId;
		uni.navigateTo({ url: `/pages/ComDlgSelections/dlgSelApproveFlowSend?billId=${fetchBillId}&billKey=${fetchBillId}&mdCode=${props.LowcodeGuid}&mdCName=${state.value?.mdInfo?.c_md_cname}&uniqueKey=${LOWCODERUNTIMEUNIQUEKEY}` }); // uniqueKey mainlowcodepcruntime
	}
	if (btnEvent?.singleTag === "SaveBill") {
		if (!hasFieldChangedRes) {
			uni.showModal({ title: "提示", content: "没有任何修改，不需要保存", showCancel: false, success: (res) => {} });
			return;
		}

		const allRequiredAry = state.value?.mainFormPanel?.Components?.filter?.(x => x?.c_hide !== "1" && x?.c_required === "1") || [];
		const allRequired = allRequiredAry?.length || allRequiredAry?.every(f => (state.value?.mainFormData?.[f?.c_code || ""] || (state.value?.mainFormData?.[f?.c_code || ""] === 0)))
		if (!allRequired) {
			uni.showModal({ title: "提示", content: "有必填项未填写！", showCancel: false, success: (res) => {} });
			return;
		}

		const allTbRequiredAry = state.value?.otherPanelShow?.Components?.filter?.(x => x?.c_hide !== "1" && x?.c_required === "1") || [];
		const allTbRequired = !allTbRequiredAry?.length || !state.value?.otherPanelData?.length;
		if (!allTbRequired) {
			uni.showModal({ title: "提示", content: "明细有必填项未填写！", showCancel: false, success: (res) => {} });
			return;
		}

		if (Object.keys(state.value.validateErrorDataPage || {})?.length) {
			// TODO 保存前的校验，提示，交互定位 现有组件无法定位
			uni.showModal({ title: "提示", content: "有不合法字段，请修改后再提交！", showCancel: false, success: (res) => {} });
			return;
		}
		const saveRes = await handleSaveBillHook({
			BillId: props.billId,
			ModuleCode: props.LowcodeGuid,
			mainData: state.value?.mainFormData,
			tableData: [state.value?.tableSaveData],
			mainTable: { tableName: state.value?.mainFormPanel?.PanelEditTableName || "", primaryKeys: state.value?.mainFormPanel?.PrimaryKeys || [] },
			detailListTable: [{ tableName: state.value.otherPanelShow?.PanelEditTableName || "", primaryKeys: state.value.otherPanelShow?.PrimaryKeys || [] }]
		});
		console.log("saveRes === ", saveRes);
		// saveRes && !btnEvent?.src && location.reload();
		if (saveRes && typeof saveRes === "string" && !btnEvent?.src) {
			state.value.billIdAfterSave = saveRes;
			uni.navigateTo({ url: `/pages/MainViews/lowcode/billDetail/index?billId=${saveRes}&LowcodeGuid=${props.LowcodeGuid}&LowcodeDetailGuid=${props.LowcodeDetailGuid}&mdInfo=${mdInfoEdit}` });
		}
		return saveRes;
	}
};

const handleAddRow = async () => {
	const panelData = state.value.otherPanelData;
	// const rowIdx = panelData?.length || 0, cSortAry = panelData?.map(r => (+r?.c_sort || 1));
	// const maxSortVal = (Array.isArray(cSortAry) && cSortAry?.length) ? Math.max(...cSortAry) : 0;
	const newRow = await generateLowcodeDef({ Components: state.value?.otherPanelShow?.Components, editTbName: state.value?.mainFormPanel?.PanelEditTableName, panelData, panelType: "3" });
	const __keyMax = Array.isArray(panelData) && panelData?.length ? Math.max(...panelData?.map(r => r?.[lowcodeRowKey])) : 0;
	const defNewRow = { ...newRow, c_id: props.billId || "", [lowcodeRowKey]: __keyMax + 1 };
	state.value.popupData = { ...defNewRow };
	state.value.editTbRowData = { ...defNewRow };
	popupRef.value?.open();
};

const handleDelRow = async (rowIdx?: number) => {
	const modalCnt = `您确认要删除当前行吗？`;	 // 删除行
	uni.showModal({ title: "提示", content: modalCnt, success: async (res) => {
		if (res.confirm) {
			// console.log("handleDelRow rowIdx", rowIdx);
			rowIdx && state.value.tableSaveData.DelList.push(state.value.otherPanelData?.[rowIdx]);
			const newOtherOtherData: { [key: string]: any } = [];
			state.value.otherPanelData?.forEach((r: any, i: number) => i !== rowIdx && newOtherOtherData.push(r));
			state.value.otherPanelData = newOtherOtherData;
			await getCellProps();
			await getOtherSubCardCellProps();
		}
	} });
};

const handleEditRow = async (rowData?: { [key: string]: any }, rowIdx?: number) => {
	// console.log("handleAddRow rowData, rowIdx", rowData, rowIdx);
	state.value.popupData = { ...rowData };
	state.value.editTbRowData = { ...rowData };
	state.value.editTbIdx = rowIdx;
	popupRef.value?.open();
};

const handlePopupClose = async ({ singleTag }) => {
	// console.log("handlePopupClose popupData ", state.value.popupData);
	if (singleTag === "重置") {
		Object.keys(state.value.popupData || {})?.forEach(k => {
			state.value.popupData[k] = state.value.editTbRowData[k];
		});
		state.value.validateErrorDataPop = {};
		return;
	}

	if (singleTag === "确认") {
		const allTbRequiredAry = state.value?.otherPanelShow?.Components?.filter?.(x => x?.c_hide !== "1" && x?.c_required === "1") || [];
		const allTbRequired = !allTbRequiredAry?.length || allTbRequiredAry?.every(f => (state.value.popupData?.[f?.c_code || ""] || (state.value.popupData?.[f?.c_code || ""] === 0)));
		if (!allTbRequired) {
			uni.showModal({ title: "提示", content: "有必填项未填写！", showCancel: false, success: (res) => {} });
			return;
		}

		if (Object.keys(state.value.validateErrorDataPop || {})?.length) {
			// TODO 保存前的校验，提示，定位 现有组件无法定位 + 处理必填
			uni.showModal({ title: "提示", content: "有不合法字段，请修改后再提交！", showCancel: false, success: (res) => {} });
			return;
		}
		if (!state.value.otherPanelData) {
			state.value.otherPanelData = [];
		}
		if (!state.value.initOtherPanelDataObj) {
			state.value.initOtherPanelDataObj = {};
		}

		const primaryKeys = state.value.otherPanelConf?.PrimaryKeys || ["c_id"];
		const needFormat = Array.isArray(primaryKeys) && primaryKeys?.length;
		const edit__Key = state.value.popupData?.[lowcodeRowKey];
		const editUniqueAry = needFormat ? primaryKeys?.map(k => state.value.popupData?.[k]) : null;
		const editUniqueKey = Array.isArray(editUniqueAry) && editUniqueAry?.length ? editUniqueAry?.join(lowcodePrimaryLink) : "";

		const isEditExitRow = +(state.value.editTbIdx || "") === state.value.editTbIdx;
		const lastEditRowData = isEditExitRow ? state.value.otherPanelData?.[+(state.value.editTbIdx || "")] : null;
		const lastEditUniqueKey = (isEditExitRow && needFormat) ? primaryKeys?.map(k => lastEditRowData?.[k])?.join(lowcodePrimaryLink) : "";

		const needRepeatCheck = !isEditExitRow || (isEditExitRow && (lastEditUniqueKey !== editUniqueKey));
		const guidPanelData = state.value.otherPanelData || [];

		const uniKeyRepeat = needFormat && needRepeatCheck && Array.isArray(guidPanelData) && Array.from(guidPanelData)?.some(r => {
			const rUniqueKey = primaryKeys?.map(k => r?.[k])?.join(lowcodePrimaryLink);
			return rUniqueKey === editUniqueKey;
		});
		if (needRepeatCheck && uniKeyRepeat) {
			const repeatMsg = `数据重复请检查（主键重复）！重复键值为：(${editUniqueAry?.join("，")})！`;
			return uni.showModal({ title: "提示", content: repeatMsg, showCancel: false, success: (res) => {} });
		}

		if (isEditExitRow) { // 表明是 对页面上已有行数据进行修改
			const rowChanged = Object.values(lastEditRowData).join(",") !== Object.values(state.value.popupData || {}).join(",");
			if (rowChanged) {
				let exitIn = false;
				state.value.otherPanelData?.splice(state.value.editTbIdx, 1);
				state.value.otherPanelData.splice(state.value.editTbIdx, 0, { ...state.value.popupData });

				if (state.value.initOtherPanelDataObj?.[lastEditUniqueKey]) {	// ModifiedList 包含 editUniqueKey 替换，否则 push
					const cacheMdList: any[] = [];	// 修改的是 接口返回的单据中已有的行数据。
					state.value.tableSaveData.ModifiedList?.forEach(r => {
						const rUniqueKey = primaryKeys?.map(k => r?.[k])?.join(lowcodePrimaryLink);
						if (editUniqueKey === rUniqueKey) {
							exitIn = true;
							return cacheMdList.push({ ...state.value.popupData });
						}
						cacheMdList.push(r);
					});
					!exitIn && cacheMdList?.push({ ...state.value.popupData });
					state.value.tableSaveData.ModifiedList = cacheMdList;

					// 需要看有没有改主键
					if (lastEditUniqueKey === editUniqueKey) { // 没改主键。 只处理 ModifiedList
					} else { // 改了主键。 需要处理 ModifiedList 和 DelList
						// 校验重复
						state.value.tableSaveData.DelList.push({ ...lastEditRowData });
					}
				} else { // 修改的是 单据中原先没有，但本次已经加到页面上的已存在行数据。
					const cacheNewList: any[] = [];
					state.value.tableSaveData.NewList?.forEach(r => {
						const rUniqueKey = primaryKeys?.map(k => r?.[k])?.join(lowcodePrimaryLink);
						if (editUniqueKey === rUniqueKey) {
							exitIn = true;
							return cacheNewList.push({ ...state.value.popupData });
						}
						cacheNewList.push(r);
					});
					!exitIn && cacheNewList?.push({ ...state.value.popupData });
					state.value.tableSaveData.NewList = cacheNewList;

					if (lastEditUniqueKey === editUniqueKey) { // 没改主键。 只处理 ModifiedList
					} else { // 改了主键
						// 校验重复
					}
				}
			}
		} else {  // 新增行
			// 校验重复
			state.value.otherPanelData.push({ ...state.value.popupData });
			state.value.tableSaveData.NewList.push({ ...state.value.popupData });
		}

		await getCellProps();
		await getOtherSubCardCellProps();
		state.value.editTbIdx = undefined;
		state.value.editTbRowData = {};
	}
	state.value.validateErrorDataPop = {};
	popupRef.value?.close();
	console.log("popupRef close state === ", state.value);
};

const fieldNeedShow = (colField: LowcodePagePanelComponentItem, proxy?: LowcodeFieldNeedShowProxy) => {
	const fieldCode = colField?.c_code || "";
	if (colField?.c_hide === "1") {
		const subPanelsEditFields = state.value.subPanelsEditFields?.[proxy?.pGuid || ""];
		if (proxy?.pGuid && subPanelsEditFields) {
			return subPanelsEditFields?.[fieldCode]?.c_hide !== "1";
		}
		return false;
	}
	const basicComponentType = ["fileupload"];
	const componentTypeFilter = basicComponentType; // (proxy?.showPattern ? [] : ["textblock"]).concat(basicComponentType);
	if (componentTypeFilter.includes(colField?.c_type || "")) {
		return false;
	}
	return true;
}

const handlePopDynamicChange = async (key: string, newVal: any, oldVal: any, proxy?: { [key: string]: any }) => {
	if (!state.value.popupData) {
		state.value.popupData = {};
	}

	state.value.popupData[key] = newVal;
	const mergeFieldAry = Object.keys(proxy?.mergeFields || {});
	if (mergeFieldAry?.length) {
		mergeFieldAry?.map(fk => (state.value.popupData[fk] = proxy?.mergeFields?.[fk]));
	}
	console.log("handlePopDynamicChangePure state.value.popupData ", state.value.popupData);

	const fieldConf = state.value.otherComponentConf?.[key] || {};
	const valType = fieldConf?.c_type === "numberinput" ? "number" : "string";
	// const validateItems = fieldConf?.c_datavalidate?.validateItems;
	const validateRes = await handleValidator({ value: newVal, valType, fieldConf, rowData: { ...state.value.popupData } });
	if (validateRes && !validateRes?.validated) {
		uni.showModal({ title: "提示", content: validateRes?.msg, showCancel: false, success: (res) => {} });
		state.value.validateErrorDataPop[key] = { oldVal: "", newVal: newVal, msg: validateRes?.msg };
		return;
	}
	delete state.value.validateErrorDataPop[key];

	const newRecord = await handleEventData({ record: { ...state.value.popupData }, fieldName: key, newValue: newVal, itemsConfig: state.value?.otherPanelShow?.Components });
	Object.keys(newRecord || {}).map(k => state.value.popupData[k] = newRecord?.[k]);
	console.log("handlePopDynamicChangePure 2222  state.value.popupData ", state.value.popupData, newRecord);
	// console.log("handlePopDynamicChange ", state.value.popupData);
};

// const handlePopDynamicChange = lowcodeDebounce(handlePopDynamicChangePure, lowcodeDebounceTime);

const handleMainDynamicChange = async (key: string, newVal: any, oldVal: any, proxy?: { [key: string]: any }) => {
	// console.log("handleMainDynamicChange proxy ", key, newVal, oldVal, proxy);
	if (!state.value.mainFormData) {
		state.value.mainFormData = {};
	}

	state.value.mainFormData[key] = newVal;
	const mergeFieldAry = Object.keys(proxy?.mergeFields || {});
	if (mergeFieldAry?.length) {
		mergeFieldAry?.map(fk => (state.value.mainFormData[fk] = proxy?.mergeFields?.[fk]));
	}

	const fieldConf = state.value.mainComponentConf?.[key] || {};
	const valType = fieldConf?.c_type === "numberinput" ? "number" : "string";
	// const validateItems = fieldConf?.c_datavalidate?.validateItems;
	const validateRes = await handleValidator({ value: newVal, valType, fieldConf, rowData: { ...state.value.mainFormData } });
	if (validateRes && !validateRes?.validated) {
		uni.showModal({ title: "提示", content: validateRes?.msg, showCancel: false, success: (res) => {} });
		state.value.validateErrorDataPage[key] = { oldVal: "", newVal: newVal, msg: validateRes?.msg };
		return;
	}
	delete state.value.validateErrorDataPage[key];

	const newRecord = await handleEventData({ record: { ...state.value.mainFormData }, fieldName: key, newValue: newVal, itemsConfig: state.value?.mainFormPanel?.Components });
	Object.keys(newRecord || {}).map(k => state.value.mainFormData[k] = newRecord?.[k]);
	await getMainSubCardCellProps();
	// console.log("handleMainDynamicChange ", newRecord, state.value.mainFormData);
};

// const handleMainDynamicChange = lowcodeDebounce(handleMainDynamicChangePure, lowcodeDebounceTime);

const handleLowCodePage = async (pageConf?: LowcodePage) => {
	const menuCFG = pageConf?.c_menuCFG || undefined;
	const filterMenus = menuCFG?.menus?.filter(m => !["AddRow", "DeleteRow", "DeleteBill"].includes(m.menuCode || ""));
	if (menuCFG && Array.isArray(filterMenus) && filterMenus.length) {
		state.value.menusCFG = filterMenus.slice(0, 4);
		state.value.menusCFGMore = filterMenus.slice(4)?.map(m => ({ text: m.menuTitle || "" }));
	}
	state.value.c_menuCFG = menuCFG?.menus;
	// if (filterMenus?.length !== menuCFG?.menus?.length) {
	// 	state.value.enableRowDelete = true;
	// }

	const enableApprove = await getRdsSysConfig("单据是否审批", state.value?.mdInfo?.c_md_cname) === "是";
	state.value.enableApprove = enableApprove;

	const topPanels: LowcodePagePanel[] = [];
	pageConf?.Panels?.forEach(p => {
		if (p?.c_ppanel_guid) {
			const ppanelGuid = p.c_ppanel_guid;
			if (!state.value?.subCardFormPanels) {
				state.value.subCardFormPanels = {};
			}
			if (!Array.isArray(state.value?.subCardFormPanels[ppanelGuid])) {
				state.value.subCardFormPanels[ppanelGuid] = [];
			}
      state.value.subCardFormPanels[ppanelGuid].push(({ ...p, ...formGridSort(p?.Components) }) as LowcodeGridRowColComponents);

			if (!state.value.subPanelsEditFields) {
				state.value.subPanelsEditFields = {};
			}
			if (!state.value.subPanelsEditFields[ppanelGuid]) {
				state.value.subPanelsEditFields[ppanelGuid] = {};
			}
			handlePanelEditFields(state.value.subPanelsEditFields[ppanelGuid], p?.Components);
		} else {
			topPanels.push(p);
		}
	});

  state.value.cIdConf = topPanels?.[0]?.Components?.find(c => c.c_code === "c_id");
	state.value.mainFormPanel = topPanels?.[0];
  // state.value.mainSubCardFormPanels = pageConf?.Panels?.filter(p => p.c_ppanel_guid === topPanels?.[0]?.c_guid);
	state.value.mainComponentConf = topPanels?.[0]?.Components?.reduce((obj, item) => ({ ...obj, [item?.c_code || ""]: item }), {});

  topPanels?.forEach((panel, pIdx) => {
		if (pIdx === 0 || !panel?.c_guid) {
			return;
		}
		// if (!state?.value?.otherPanelConf) {
		// 	state.value.otherPanelConf = {};
		// }
		// state.value.otherPanelConf = panel;
		state.value.otherPanelShow = panel;
    state.value.otherPanelConf = ({ ...panel, ...formGridSort(panel?.Components) }) as LowcodeGridRowColComponents;
		state.value.otherComponentConf = panel?.Components?.reduce((obj, item) => ({ ...obj, [item?.c_code || ""]: item }), {});
	});
};

const handleSystemInfo = () => {
	const systemInfo = getSystemInfo();
	state.value.systemInfo = systemInfo;
};

const getMainCellProps = async () => {
	// if (!state.value?.mainFormData || !state.value?.mainFormPanel?.Components?.length) {
	// 	return;
	// }
  // if (!state.value?.mainCellProps) {
  //   state.value.mainCellProps = {};
  // }
	// for (let fIdx = 0; fIdx < state.value?.mainFormPanel?.Components?.length; fIdx++) {
  //   const mainComponents = state.value?.mainFormPanel?.Components;
  //   const colField = mainComponents?.[fIdx];
  //   if (colField) {
  //     state.value.mainCellProps[colField?.c_code || ""] = await getComponentProps({ confObject: colField, dataObject: state.value?.mainFormData });
  //   }
	// }
};

const getCellProps = async () => {
	if (!state.value?.otherPanelData?.length || !state.value?.otherPanelConf?.Components?.length) {
		return;
	}
	for (let idx = 0; idx < state.value?.otherPanelData?.length; idx++) {
		const rowData = state.value?.otherPanelData[idx];
		for (let fIdx = 0; fIdx < state.value?.otherPanelConf?.Components?.length; fIdx++) {
			const rowCols = state.value?.otherPanelConf?.Components[fIdx];
			for (let cfIdx = 0; cfIdx < rowCols?.length; cfIdx++) {
				if (!state.value?.cellProps) {
					state.value.cellProps = {};
				}
				const colField = rowCols[cfIdx];
				state.value.cellProps[idx+'_'+fIdx+'_'+cfIdx] = await getComponentProps({ componentType: 'EuiText', confObject: colField, dataObject: rowData, parentSrc: "3" });
			}
		}
	}
};

const fillSubCellProps = async (subKey: string, subCardFormPanel?: LowcodeGridRowColComponents, formData?: { [key: string]: any }, parentSrc?: string) => {
	if (!formData || !subCardFormPanel?.Components?.length) {
		return;
	}
	for (let fIdx = 0; fIdx < subCardFormPanel?.Components?.length; fIdx++) {
		const rowCols = subCardFormPanel?.Components[fIdx];
		for (let cfIdx = 0; cfIdx < rowCols?.length; cfIdx++) {
			if (!state.value?.subCellProps) {
				state.value.subCellProps = {};
			}
			const colField = rowCols[cfIdx];
			state.value.subCellProps[subKey+fIdx+'_'+cfIdx] = await getComponentProps({ componentType: 'EuiText', confObject: colField, dataObject: formData, parentSrc });
		}
	}
}

const getMainSubCardCellProps = async () => {
	const mainSubCardFormPanels = getMainSubCardFormPanels();
	for (let i = 0; i < (mainSubCardFormPanels?.length || 0); i++) {
		const mainSubCardFormPanel = mainSubCardFormPanels?.[i];
		const subKey = "main_sub" + (mainSubCardFormPanel?.c_guid || "");
		await fillSubCellProps(subKey, mainSubCardFormPanel, state.value?.mainFormData);
	}
};

const getOtherSubCardCellProps = async () => {
	const otherSubCardFormPanels = getOtherSubCardFormPanels();
	for (let rowIdx = 0; rowIdx < (state.value?.otherPanelData?.length || 0); rowIdx++) {
		const rowData = state.value?.otherPanelData?.[rowIdx];
		for (let i = 0; i < (otherSubCardFormPanels?.length || 0); i++) {
			const otherSubCardFormPanel = otherSubCardFormPanels?.[i];
			const subKey = "other_sub" + (otherSubCardFormPanel?.c_guid || "") + rowIdx + "_";
			await fillSubCellProps(subKey, otherSubCardFormPanel, rowData, "3");
		}
	}
};

const initShowData = async (fetchProxy?: FetchMdBillDetailProxy) => {
	await getMainCellProps();
	await getCellProps();
	await getMainSubCardCellProps();
	await getOtherSubCardCellProps();

  // 监听字段值变化，重新给 CardTitle 赋值
  state.value.mainCardTitle = getMainCardTitle();
  state.value.otherCardTitle = getOtherCardTitle();

	if (fetchProxy?.isOnLoad) {
		const userInfoPage = uni.createSelectorQuery().select(".lowcode-nav-wrap");
		userInfoPage.boundingClientRect(rect => {
			(state.value.navWrapRect = (rect as LowcodeRect));
			const basicPageH = Math.floor(state.value.systemInfo?.windowHeight - (state.value?.navWrapRect?.height || 0));
			state.value.createPopupStyle = { height: Math.floor(basicPageH * 0.9 - 100) + "px" };
			state.value.editWrapStyle = { "max-height": (basicPageH - 65) + "px", "overflow-y": "auto" };
		}).exec();
	}
	console.log("edit init show Data");
};

const fetchDetailData = async (fetchProxy?: FetchMdBillDetailProxy) => {
  if (!props?.billId) {
		const cacheMainPanel = state.value?.mainFormPanel;
    const initMainData = await generateLowcodeDef({ Components: cacheMainPanel?.Components, editTbName: cacheMainPanel?.PanelEditTableName, panelType: cacheMainPanel?.c_type });
    state.value.mainFormData = { ...initMainData };
		state.value.initMainFormData = { ...initMainData };
		state.value.otherPanelData = [];
		state.value.initOtherPanelData = [];
    await initShowData(fetchProxy);
    return;
  }
	uni.showLoading({ title: "查询中...", mask: true});
	const fetchReq = { BillId: props.billId };
	const fetchReqProxy = { ModuleCode: props.LowcodeGuid };
	const fetchRes = await service.request<FetchDetailDataReq, FetchDetailDataRes>(LOWCODERUNTIMEUNIQUEKEY, "EnjoyBillQuery", fetchReq, "", "", fetchReqProxy);
	uni.hideLoading();
	if (!fetchRes) {
		return;
	}
	Object.keys(fetchRes || {})?.forEach((k, kIdx) => {
		const kData = fetchRes[k];
		if (k === "ds") {
			const initMainData = (Array.isArray(kData) ? kData[0] : kData) || {};
			state.value.mainFormData = { ...initMainData };
			state.value.initMainFormData = { ...initMainData };
			return;
		}

		const tableData = (kData || [])?.map((r, rIdx) => ({ ...r, [lowcodeRowKey]: rIdx }));
		const primaryKeys = state.value.otherPanelConf?.PrimaryKeys || [];
		const needFormat = Array.isArray(primaryKeys) && primaryKeys?.length;
		state.value.otherPanelData = (kData || [])?.map((r, rIdx) => ({ ...r, [lowcodeRowKey]: rIdx }));
		state.value.initOtherPanelData = (kData || [])?.map((r, rIdx) => ({ ...r, [lowcodeRowKey]: rIdx }));
		state.value.initOtherPanelDataObj = tableData?.reduce((o, r) => {
			const rUniKey = needFormat ? primaryKeys?.map(k => r?.[k])?.join(lowcodePrimaryLink) : "";
			return ({ ...o, [rUniKey]: r });
		}, {});
	});
	await initShowData(fetchProxy);
};

const fetchDetailPage = async (fetchProxy?: FetchMdBillDetailProxy) => {
	const fetchReqProxy = { ModuleCode: props.LowcodeGuid };
	const fetchReq = { LowcodeGuid: props.LowcodeGuid || "", LowcodeDetailGuid: props.LowcodeDetailGuid || "" };
	uni.showLoading({ title: "查询中...", mask: true});
	const fetchRes = await service.request<BillDetailFetchReq, BillDetailFetchRes>(LOWCODEUNIQUEKEY, "FindMobileRuntimeDetailPage", fetchReq, "", "", fetchReqProxy);
	uni.hideLoading();
	if (fetchRes !== undefined) {
		await handleLowCodePage(fetchRes?.LowcodePage);
		await fetchDetailData(fetchProxy);
	}
	state.value.lowcodeInfo = fetchRes?.Lowcode;
};

const handleRefreshPage = () => {
	console.log("state.value edit ", state.value)
	const mdInfoEdit = typeof props?.mdInfo === "string" ? props?.mdInfo : (props?.mdInfo ? JSON.stringify(props?.mdInfo) : "");
	setTimeout(() => {
		uni.navigateTo({ url: `/pages/MainViews/lowcode/billDetail/index?billId=${state.value.billIdAfterSave}&LowcodeGuid=${props.LowcodeGuid}&LowcodeDetailGuid=${props.LowcodeDetailGuid}&mdInfo=${mdInfoEdit}` });
	}, 1000);
	// uni.navigateTo({ url: `/pages/MainViews/lowcode/billDetail/index?billId=${state.value.billIdAfterSave}&LowcodeGuid=${props.LowcodeGuid}&LowcodeDetailGuid=${props.LowcodeDetailGuid}&mdInfo=${mdInfoEdit}` });
};

onLoad(async (proxy) => {
	console.log("onLoad proxy ", proxy, props);
	uni.$on("RefreshPage", handleRefreshPage);
  state.value.mdInfo = props.mdInfo ? JSON.parse(props.mdInfo || "") : null;
	state.value.pageTitle = props?.billId ? "编辑" : "新增";

	state.value.validateErrorDataPop = {};
	state.value.validateErrorDataPage = {};

	await initRdsDict();
  handleSystemInfo();
	fetchDetailPage({ isOnLoad: true });
});

</script>

<style scoped lang="scss">
@import '@/main.scss';
@import "../index.scss";
@import "./index.scss";
</style>
